home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
mac
/
files
/
misc
/
icom.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-25
|
9KB
|
436 lines
15-Nov-87 22:41:42-MST,9407;000000000000
Date: Thursday, 21 August 1986 01:45-MDT
From: Phil Karn <karn at ka9q.bellcore.COM>
To: info-hams
Re: Controlling ICOM radios from the IBM PC - Part 2 (source code)
Here's the source code I wrote for controlling the ICOM radios through my PC
clone's printer port. Note that all frequencies are represented in hertz,
using longs; this makes things more consistent since different radio functions
require different precision.
-----------
/* icom.c
* Library functions for driving the ICOM computer interface
* Copyright 1986 by Phil Karn, KA9Q
* Permission granted for free noncommercial copying and use by
* licensed radio amateurs.
*/
#include "icom.h"
char *modes[] = {
"LSB", /* 0 */
"USB", /* 1 */
"AM", /* 2 */
"CW", /* 3 */
"RTTY", /* 4 */
"FM", /* 5 */
"CW Narrow", /* 6 */
"RTTY Narrow", /* 7 */
"lsb", /* 8 */
"usb", /* 9 */
"am", /* a */
"cw narrow", /* b */
"rtty narrow", /* c */
"fm", /* d */
"0xe", /* e */
"0xf" /* f */
};
/* Read band */
int
read_band(freq,lower,upper)
long freq; /* Used just to select the radio */
long *lower,*upper; /* Band limits returned through here */
{
register int i;
start_cmd();
if(send_byte(BAND | band(freq)) < 0){
end_cmd();
return -1;
}
*upper = 0;
read_byte(); /* Toss opening delim */
for(i=0;i<6;i++)
*upper = *upper * 10 + (read_byte() & 0xf);
read_byte(); /* Toss closing delim */
*upper *= 10000; /* Convert to hertz */
*lower = 0;
read_byte(); /* Toss second opening delim */
for(i=0;i<6;i++)
*lower = *lower * 10 + (read_byte() & 0xf);
read_byte(); /* Toss second closing delim */
*lower *= 10000; /* Convert to hertz */
end_cmd();
return 0;
}
/* Set frequency; the proper radio is automatically selected */
int
set_freq(freq)
long freq; /* Frequency, hertz */
{
register int i;
char fstr[15];
start_cmd();
if(send_byte(FREQ | band(freq)) < 0){
end_cmd();
return -1;
}
send_byte(FREQ | 0xd);
sprintf(fstr,"%09ld",freq/10);
for(i=0;i<9;i++)
send_byte(FREQ | (fstr[i] - '0'));
send_byte(FREQ | 0xe);
end_cmd();
return 0;
}
/* Read frequency */
long
read_freq(freq)
long freq; /* For band selection only */
{
register int i;
start_cmd();
if(send_byte(FREQ | band(freq)) < 0){
end_cmd();
return -1;
}
if(read_byte() < 0) /* Discard opening delimiter */
return -1;
freq = 0;
for(i=0;i<9;i++){
freq = freq * 10 + (read_byte() & 0xf);
}
read_byte(); /* Discard closing delimiter */
freq *= 10;
end_cmd();
return freq;
}
/* set mode */
int
set_mode(freq,mode)
long freq; /* For radio selection */
int mode; /* Desired operating mode */
{
start_cmd();
if(send_byte(MODE | band(freq)) < 0){
end_cmd();
return -1;
}
send_byte(MODE | 0xd);
send_byte(MODE | mode);
send_byte(MODE | 0xe);
end_cmd();
return 0;
}
/* Return current mode */
int
read_mode(freq)
long freq; /* For radio selection */
{
int c;
start_cmd();
if(send_byte(MODE | band(freq)) < 0){
end_cmd();
return -1;
}
read_byte();
c = read_byte();
read_byte();
end_cmd();
return c & 0xf;
}
/* Set offset */
int
set_offset(freq,offset)
long freq; /* For radio selection */
long offset; /* Offset, hertz */
{
register int i;
char fstr[15];
start_cmd();
if(send_byte(OFFSET | band(freq)) < 0){
end_cmd();
return -1;
}
send_byte(OFFSET | 0xd);
sprintf(fstr,"%09ld",freq/1000);
for(i=0;i<9;i++)
send_byte(OFFSET | (fstr[i] - '0'));
send_byte(OFFSET | 0xe);
end_cmd();
return 0;
}
/* Read offset */
long
read_offset(freq)
long freq; /* For radio selection */
{
register int i;
long offset;
start_cmd();
if(send_byte(OFFSET | band(freq)) < 0){
end_cmd();
return -1;
}
read_byte(); /* Discard opening delimiter */
offset = 0;
for(i=0;i<9;i++)
offset = offset * 10 + (read_byte() & 0xf);
read_byte(); /* Discard closing delimiter */
offset *= 1000;
end_cmd();
return offset;
}
/* Select memory channel or vfo */
int
set_mem(freq,val)
long freq; /* For radio selection */
int val; /* Desired VFO/channel number */
{
start_cmd();
if(send_byte(MEMVFO | band(freq)) < 0){
end_cmd();
return -1;
}
send_byte(MEMVFO | 0xd);
send_byte(MEMVFO | ((val >> 4) & 0xf)); /* tens digit */
send_byte(MEMVFO | (val & 0xf)); /* units digit */
send_byte(MEMVFO | 0xe);
end_cmd();
return 0;
}
/* Transfer between VFO and memory */
int
transfer(freq,dir)
long freq; /* For radio selection */
int dir; /* Desired direction of transfer */
{
start_cmd();
if(send_byte(MEMRW | band(freq)) < 0){
end_cmd();
return -1;
}
send_byte(MEMRW | 0xd);
send_byte(MEMRW | dir);
send_byte(MEMRW | 0xe);
end_cmd();
return 0;
}
/* Set band
* Uses the hack by NG6Q in April 1986 Ham Radio
* Warning: untested (I don't have a 751).
*/
int
set_band(freq,b)
long freq; /* For radio selection */
int b; /* Desired band */
{
long funny;
set_mem(freq,38); /* Select channel 38 */
funny = (freq/1000000) * 1000000; /* Truncate to Mhz */
funny += 100000 * b; /* Desired band goes in 100khz digit*/
set_freq(funny);
transfer(freq,WRITE); /* Store in memory */
set_mem(freq,0); /* Go back to VFO */
transfer(freq,READ); /* Get the funny value */
set_freq(freq); /* Put in the one we really want */
return 0;
}
/* The following are internal subroutines that perform the low-level
* parts of the host/radio protocol. These can be "static" if you wish.
*/
/* Send individual byte of a message */
int
send_byte(c)
char c;
{
register int i;
outportb(I_DATA,c);
/* Turn on WP and output mode in addition to SRQ */
outportb(I_CTL,CTL_POL^(SRQ_CMD|WP_CMD|OUTPUT_MODE));
/* Wait for DAV to go active low */
for(i=TIMEOUT;i != 0;i--){
if((inportb(I_DAV) & DAV_STAT) == 0)
break;
}
if(i == 0){
outportb(I_CTL,CTL_POL);
printf("sendbyte fail\n");
return -1;
}
/* Drop WP and output mode, keeping SRQ active */
outportb(I_CTL,CTL_POL^SRQ_CMD);
/* Wait for DAV to go inactive high */
for(i=TIMEOUT;i != 0;i--){
if((inportb(I_DAV) & DAV_STAT) != 0)
break;
}
if(i == 0){
outportb(I_CTL,CTL_POL);
printf("sendbyte fail 2\n");
return -2;
}
return 0;
}
/* Read individual byte within a message */
int
read_byte()
{
register int i;
register int c;
/* Configure for input */
outportb(I_CTL,CTL_POL^(RP_CMD|SRQ_CMD));
/* Wait for DAV to go active low */
for(i=TIMEOUT;i != 0;i--){
if((inportb(I_DAV) & DAV_STAT) == 0)
break;
}
if(i == 0){
outportb(I_CTL,CTL_POL);
printf("read fail\n");
return -1;
}
/* Read data byte from bus */
c = inportb(I_DATA);
/* Drop RP, keeping SRQ active */
outportb(I_CTL,CTL_POL^SRQ_CMD);
/* Wait for DAV to go inactive high */
for(i=TIMEOUT;i != 0;i--){
if((inportb(I_DAV) & DAV_STAT) != 0)
break;
}
if(i == 0){
outportb(I_CTL,CTL_POL);
printf("read fail 2\n");
return -2;
}
return c & 0xff;
}
/* Derive band number from frequency */
int
band(freq)
register long freq;
{
if(freq >= 1200000000){
return MHZ_1200;
} else if(freq >= 420000000){
return MHZ_430;
} else if(freq >= 220000000){
return MHZ_220;
} else if(freq >= 140000000){
return MHZ_144;
} else if(freq >= 50000000){
return MHZ_50;
} else
return HF;
}
/* Begin a message */
start_cmd()
{
/* Assert SRQ */
outportb(I_CTL,CTL_POL^SRQ_CMD);
}
/* End a message */
end_cmd()
{
register int i;
/* Wait a little bit */
for(i=WAIT;i != 0;i--)
;
/* Deactivate SRQ */
outportb(I_CTL,CTL_POL);
}
-----------------
/* icom.h
* Definitions for the ICOM library functions
* 21 Aug 1986
* Phil Karn, KA9Q
*/
/* System-dependent constants; edit to taste */
/* Port addresses */
#define I_DATA 0x3bc /* Data I/O port */
#define I_CTL 0x3be /* Control port (output) */
#define I_DAV 0x3bd /* Data available port (input) */
/* Bits within I_DAV */
#define DAV_STAT 0x40
#define DAV_POL 0x40 /* DAV is negative polarity */
/* Bits within I_CTL */
#define OUTPUT_MODE 0x20
#define RP_CMD 0x8
#define WP_CMD 0x2
#define SRQ_CMD 0x1
/* Specify any bits in I_CTL which are negative logic.
* Output mode, RP and WP are negative logic; SRQ is positive
*/
#define CTL_POL (OUTPUT_MODE|RP_CMD|WP_CMD)
/* These two values were found experimentally to work on an 8-MHz 8088
* Increase WAIT if you get frequent timeouts or protocol lockups
*/
#define TIMEOUT 65535 /* Timeout on a read/write operation */
#define WAIT 1100 /* Delay at end of sequence */
/* The following definitions are fixed by the ICOM design; they should not
* have to be changed.
*/
/* Commands */
#define BAND 0x10
#define FREQ 0x20
#define MODE 0x30
#define OFFSET 0x40
#define MEMVFO 0x50
#define MEMRW 0x60
/* Addresses */
#define HF 0x1 /* IC-71 or IC-751 */
#define MHZ_50 0x2
#define MHZ_144 0x3 /* IC-271 */
#define MHZ_220 0x4
#define MHZ_430 0x5 /* IC-471 */
#define MHZ_1200 0x6 /* IC-1271 */
/* Modes */
#define LSB 0
#define USB 1
#define AM 2
#define CW 3
#define RTTY 4
#define FM 5
#define CWN 6
#define RTTYN 7
#define WRITE 1 /* VFO to memory */
#define READ 2 /* Memory to VFO */
long read_freq();
--------------
End of code